<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>


  <script>
   /* 
    使用构造函数和ES6的类设计并测试以下需要
      需求1: 
        现在2个人, 都有姓名与年龄(值自己指定), 都能自我介绍自己的姓名和年龄
      需求2: 
        现在又有了一个学生, 它有身价的属性, 能介绍它的所有信息
        又有一个老师, 它有教授课程的属性, 能介绍它的所有信息
  */
    /* 
    基于构造函数的 原型链 + 借用构造函数的组合继承
      让子类型的原型指向父类型的实例
      让子类型的原型对象的constructor指向子类型
      借用父类型的构造函数, 用来一次性初始化多个同名的属性  ==> 简化了编码 
    */

    function Person(name, age) {
      this.name = name
      this.age = age
      // this.sayInfo = function () {
      //   console.log(`我叫${this.name}, 今年${this.age}`)
      // }
    }

    Person.prototype.sayInfo = function () {
      console.log(`我叫${this.name}, 今年${this.age}`)
    }

    // const p1 = new Person('tom', 12)
    // console.log(p1.name, p1.age)
    // p1.sayInfo()
    // const p2 = new Person('Jack', 13)
    // console.log(p2.name, p2.age)
    // p2.sayInfo()

    function Student(name, age, price) {
      // this.name = name
      // this.age = age
      /* 借用父类型的构造函数, 用来一次性初始化多个同名的属性  ==> 简化了编码  */
      Person.call(this, name, age) // 相当于this.Person(name, age)
      
      this.price = price
    }

    /* 让子类型的原型指向父类型的实例 */
    Student.prototype = new Person()
    /* 让子类型的原型对象的constructor指向子类型 */
    Student.prototype.constructor = Student

    /* 重写从父类型继承来的方法 */
    Student.prototype.sayInfo = function () {
      console.log(`我叫${this.name}, 今年${this.age}, 月入${this.price}`)
    }

    const s = new Student('A', 23, 15000)
    console.log(s.name, s.age, s.price)
    s.sayInfo()
    console.log(s)
    console.log(s.constructor) // Student


  </script>

  <script>
    class Person2 {
      constructor (name, age) {
        this.name = name
        this.age = age
      }

      sayInfo () { // 添加到原型对象上
        console.log(`我叫${this.name}, 今年${this.age}`)
      }
    }

    class Teacher extends Person2 {
      constructor (name, age, course) {
        super(name, age)  // 相当于前面的借用构造函数
        this.course = course
      }

      // 重写方法
      sayInfo () { // 添加到原型对象上
        console.log(`我叫${this.name}, 今年${this.age}, 教授${this.course}`)
      }
    }

    const t = new Teacher('B', 30, '前端')
    console.log(t.name, t.age, t.course)
    t.sayInfo()
    console.log(t.constructor)

    // 专门针对某个对象
    const obj = {m: 1}
    // 创建一个obj的子对象   ==> 新对象的隐式原型对象是obj
    const obj2 = Object.create(obj)
    console.log(obj2, obj2.m)

    // 让已有的对象成为另一个已有对象的子对象
    const obj3 = {n: 3}
    obj3.__proto__ = obj
    console.log(obj3, obj3.m)

    // VC和Vue的关系: VC的原型对象的原型对象是Vue的原型对象

  </script>
  
</body>
</html>